package com.seven.logproducer.service;


import com.seven.logproducer.annotation.LogAnno;
import com.seven.logproducer.enums.LogTypeEnum;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Component
@Aspect
public class LogSender {
    //系统换行符
    //public static String newLine = System.getProperty("line.separator");
    @Value("${spring.application.name}")
    private String serverName;
    @Value("${auction.exchange-name}")
    private String exchangeName;
    @Value("${auction.routekey}")
    private String routekey;
    @Value("${auction.user-attr}")
    private String userId;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

    @AfterReturning(value = "@annotation(logAnno)")
    public void afterReturning(JoinPoint point, LogAnno logAnno) {
        Map msg = getBaseInfo(point,logAnno.logType());
        //设置消息ID
        CorrelationData data = new CorrelationData();
        data.setId(UUID.randomUUID().toString());

        rabbitTemplate.convertAndSend(exchangeName,routekey, msg, data);
    }

    private Map getBaseInfo(JoinPoint point, LogTypeEnum logTypeEnum){
        Map map = new HashMap();
        //日志类型
        map.put("type",logTypeEnum.getCode());
        //当前时间
        map.put("time",simpleDateFormat.format(new Date()));
        //服务名称
        map.put("client",serverName);
        //调用ip
        map.put("ip",getIpAndUserId());
        MethodSignature signature = (MethodSignature)point.getSignature();
        // 方法名
        map.put("method",signature.getName());
        // 操作
        map.put("operate",signature.getMethod().getAnnotation(LogAnno.class).msg());
        // 参数
        Object[] params = point.getArgs();
        if (params != null && params.length>0){
            map.put("params",params);
        }else {
            map.put("params","null");
        }
        return map;
    }



    private String getIpAndUserId() {
        String attributeName = userId;
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        String ipAddress;
        ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("X-Real-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
        }
        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
            // = 15
            if (ipAddress.indexOf(",") > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
            }
        }
        Object userId = request.getSession().getAttribute(attributeName);
        //不涉及NPE，不判断null
        //使用localhost:8080 ip地址会是0:0:0:0:0:0:0:1
        return ipAddress + "--" + userId;
    }

}
